home *** CD-ROM | disk | FTP | other *** search
- /*
- Sherlock run-time routines.
-
- bug fix: 10/18/88: sl_visit().
- bug fix: 2/10/89: sl_lout().
- added: 2/10/89: sl_uiout() and sl_ulout().
- bug fix: 4/19/89: sl_set().
- bug fix: 6/27/89: sl_check().
- lib fix: 6/30/89: ltoa, itoa redefined.
- added: 8/3/89: sl_adjust(). Used only by sl_dump().
- bug fix: 4/17/90: sl_level made a global var as in manual.
-
- Mark I version started: September 26, 1985
- Mark II version started: September 8, 1986
-
- Source: sherlock.c
- Versions:
-
- 0.6a June 8, 1988
- 0.7 June 21, 1988
- 0.7c June 28, 1988
- 0.8 July 14, 1988
- 1.0 July 21, 1988
- 1.1 February 14, 1989
- 1.2 February 27, 1989
- 1.3 April 19, 1989
- 1.4 June 27, 1989
- 1.5 August 4, 1989
- 1.6 April 17, 1990
- 1.7 June 15, 1991 First Public Domain Version
-
-
- PUBLIC DOMAIN SOFTWARE
-
- Sherlock, including the SPP, SDEL and SDIF programs, was placed in
- the public domain on June 15, 1991, by its author,
-
- Edward K. Ream
- 166 North Prospect Ave.
- Madison, WI 53705.
- (608) 257-0802
-
- Sherlock may be used for any commercial or non-commercial purpose.
-
-
- DISCLAIMER OF WARRANTIES
-
- Edward K. Ream (Ream) specifically disclaims all warranties,
- expressed or implied, with respect to this computer software,
- including but not limited to implied warranties of merchantability
- and fitness for a particular purpose. In no event shall Ream be
- liable for any loss of profit or any commercial damage, including
- but not limited to special, incidental consequential or other damages.
-
-
- This file has the following parts:
- 1. Data structures and definitions.
- 2. Internal (static) routines.
- 3. Externally visible routines common to Mark I and Mark I versions.
- 4. Mark I versions of routines.
- 5. Mark II versions of routines.
- 6. Output routines
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <process.h>
- #include <string.h>
- #include <ctype.h>
-
- /* most Compilers don't have itoa() or ltoa */
- #define itoa(a, b, c) sprintf(b, "%d", a);
- #define ltoa(a, b, c) sprintf(b, "%ld", a);
-
- #define SL_VERSION_NAME "1.7"
-
- #define STAT_FLAG TRUE
- #define NO_STAT_FLAG FALSE
- #define ENTRY_FLAG TRUE
- #define NO_ENTRY_FLAG FALSE
-
- /*
- Define this constant if your compiler allows function prototypes.
- */
- #define HAS_ANSI_PROTOTYPE 1
-
- /*
- Select which version of the macros to define.
-
- The Mark I versions call sl_find() EVERY time to determine whether
- the tracepoint has been enabled. The Mark II versions call
- sl_find() only on the initial encounter with the tracepoint.
-
- The difference in speed between the Mark I and Mark II versions can
- be large. Use the Mark I version of the routines only if you are
- forced to do so by problems with the compiler you are using. All
- standard C compilers should be able to handle the Mark II version.
- */
-
- #define MARKI 1
- #define MARKII 1
-
- /*
- ========== PART 1 ==========
- Data structures and definitions.
- */
-
- /*
- Define constants that enable output for debugging the Sherlock code
- itself. Normally, these constants should be commented out.
-
- BUG_STATS: enables printing of internal statistics by sl_dump().
- BUG_HASH_DUMP: enables printing of internal statistics relating to
- the hash table.
- BUG_DEBUG: enables printing of internal tracing messages.
-
- The STATS macro is for use ONLY within this file. It expands the
- statement supplied as its actual parameter only if BUG_STATS variable
- is defined. Typically, the actual parameter is a statement which bumps
- an internal tracing statistic.
-
- The DEBUG macro is for use ONLY within this file. It expands the
- statement supplied as its actual parameter only if the BUG_DEBUG
- variable is defined. Typically, the actual parameter is a printf()
- statement used to trace the internal workings of the routines on this
- file.
- */
-
- /* -----
- #define BUG_STATS 1
- #define BUG_DEBUG 1
- ----- */
-
- #ifdef BUG_STATS
- #define STATS(statement) statement
- #else
- #define STATS(statement)
- #endif
-
- #ifdef BUG_DEBUG
- #define DEBUG(statement) statement
- #else
- #define DEBUG(statement)
- #endif
-
- /*
- Define various constants.
- */
- #define TRUE (1)
- #define FALSE (0)
- #define BAD_EXIT (1)
-
- /*
- Define the format of statistics nodes.
-
- These nodes are used to keep all information related to tracepoints.
- There is exactly one node per tracepoint, regardless of how many
- times a tracepoint name appears throughout the code.
- */
- static struct stat {
- struct stat * next; /* pointer to next bucket. */
- struct stat * alpha; /* alphabetical list. */
- char * name; /* pointer to checkpoint name. */
- long n_stat; /* # of calls to macros. */
- long n_disable; /* # of prints to skip or 0. */
- long n_times; /* # of profiler ticks. */
- long n_2times; /* Cumulative ticks. */
- int trace; /* trace flag. */
- };
-
- /*
- Define a dummy node used as a target for statistics gathering
- before the first Sherlock macro is seen.
-
- The dummy node also is used as the list header when the nodes are
- alphabetized by sl_dump().
- */
- static struct stat a_list;
-
- /*
- Define a (fixed size) array of statistics nodes. All stat nodes are
- allocated from this array. We do NOT call dynamic storage allocation,
- (such as malloc() or calloc()) to get node storage so as not to
- disturb memory while tracing.
-
- The sl__nodes [] array holds all the nodes.
- The cur_stat variable counts how many entries in sl__nodes [] have
- already been allocated.
- */
-
- #define MAX_STAT 500
- static struct stat sl__nodes [MAX_STAT]; /* Static node table. */
- static int cur_stat = 0;
-
- /*
- Define a (fixed size) array used to keep track of nesting of Sherlock
- macros. ENTER macros push pointers to stat nodes on the stack. EXITxx
- macros pop entries from the stack. Non-cumulative timing statistics
- only increment the top of the stack. Cumulative timing statistics
- increment all entries on the stack.
-
- The sl_level variable does double duty. It keeps track of the top
- entry on the call_stack and it is used to indent output to reflect the
- current nesting level.
- */
- #define MAX_BUG_LEVEL 100
- static struct stat * call_stack [MAX_BUG_LEVEL];
-
- /* This is a global variable. */
- int sl_level = 0;
-
- /*
- Define the hash table used to speed the search of statistics nodes.
-
- The 'next' field of each stat node chains together all nodes with
- the same hash value.
- */
-
- #define MAX_HASH 241
- static struct stat * hash_tab [MAX_HASH];
-
- /*
- Define the list of names of wildcards which have been enabled from
- the command line or via calls to sl_on or sl_off(). This list is
- used by sl_new() to determine whether tracing is enabled or not.
-
- As wildcards are seen, they are added to the HEAD of the list, which
- essentially means that the list is searched in REVERSE order for
- matches. This is best, since the scan of the list can stop with the
- first match found, rather than having to scan the whole list.
- */
- static struct stat * wildcard = NULL; /* Head of wildcard list. */
-
- /*
- The troff variable suppress the operation of all STAT, TICK, TRACE
- TRACEP and RETURN_xxx macros. The troff variable is set if "--trace"
- is seen on the command line or if sl_off("trace") is seen.
-
- The only way of re-enabling Sherlock's macros after troff becomes
- TRUE is to execute sl_on("trace"). Note that the call to sl_on()
- must not occur inside a TRACE or TRACEP macro!!
- */
- static int troff = FALSE; /* TRUE if all tracing disabled. */
-
- /*
- The check_s variable contains of the name of the macro currently
- executing. It is made global so as to avoid the overhead of passing
- extra parameters to sl_set() and sl_check().
- */
- static char * check_s = NULL; /* Name of current macro. */
-
- /*
- Define local and global "disable counts."
-
- The disable variable contains a disable count which is associated
- with a single variable. The g_disable variable contains the global
- disable count. Both disable and g_disable are set by sl_set() and
- used by sl_new() when new nodes are created.
-
- Local disable counts are set by preceeding the name of a tracpoint by
- a number. For example, --100xyz sets the local disable count of xyz
- to 100. The single global disable count is set by following a prefix
- by a number alone. For example, --100 sets the global disable count
- to 100.
-
- Disable counts suppress the operation of all tracing macros.
- Each time such a macro is encounted, a check is made of both the
- global disable count and the local disable count associated with the
- tracepoint. Both global and local counts are decremented as long as
- either or both are non-zero.
- */
- static long disable = 0; /* Local disable count. */
- static long g_disable = 0; /* Global disable printing counter. */
-
- /*
- Define globals used to communicate with the Interrupt Handler.
-
- The interrupt handler allows Sherlock macros to gather timing
- statistics. The interrupt handler code (in PRF.ASM) is required
- only if the TIME_STATS variable is defined.
-
- WARNING: By necessity, the interrupt handler contains
- MACHINE DEPENDENT CODE. Using this code is not
- guarranteed to work and may cause your system to
- crash. See further warnings in file PRF.ASM.
-
- TIME_STATS enables code which gathers timing statistics.
-
- sl_count a global variable which is incremented each time
- the interrupt handle is executed.
-
- sl_speed The 'speed-up factor' used to speed up the system
- timer to acheive speeds greater than the default
- speed of 18.2 clock ticks per second.
-
- As you can imagine, increasing the speed of the system
- clock is potentially a MACHINE DEPENDENT OPERATION.
- However, the interrupt handler masks the speedup from
- the rest of the system by passing only selected ticks
- on to the old tick routine.
-
- A setting of 55 for sl_speed gives about
- 1 time/tick per msec. (assuming 18.2 clock ticks/sec.)
- */
-
- /* comment out -----
- #define TIME_STATS 1
- ----- end comment out */
-
- unsigned long sl_count = 0; /* Timing count. */
- unsigned int sl_speed = 55; /* Default clock speed. */
-
- /*
- Define internal tracing variables.
-
- The variables whose names begin with t_ are used only if BUG_STATS
- defined. They count how many times Sherlock's routines are called.
-
- The bin array is used to count the number of hash chains of there are
- of a given length. bin [i] counts the number of chains in the hash
- table with length i. bin [10] counts the number of chains with length
- 10 or more. Very few chains typically contain two or more elements, so
- this small array gives acceptable statistics.
- */
-
- /* -----
- #define BUG_HASH_DUMP 1
- ----- */
-
- #ifdef BUG_HASH_DUMP
- static int bin[10];
- #endif
-
- #ifdef BUG_STATS
-
- static long t_buffer = 0;
- static long t_check = 0;
- static long t_cmp = 0;
- static long t_eq = 0;
- static long t_find = 0;
- static long t_hash = 0;
- static long t_init = 0;
- static long t_match = 0;
- static long t_new = 0;
- static long t_on = 0;
- static long t_off = 0;
-
- static long t_bstat = 0;
- static long t_btick = 0;
- static long t_btrace = 0;
- static long t_ntick = 0;
- static long t_ntrace = 0;
- static long t_ptrace = 0;
- static long t_pbtrace = 0;
- static long t_pntrace = 0;
- static long t_pxtrace = 0;
- static long t_set = 0;
- static long t_stat = 0;
- static long t_tick = 0;
- static long t_trace = 0;
- static long t_xtrace = 0;
- static long t_wild = 0;
-
- #endif
-
- /*
- Forward declarations of external routines.
- They are needed because sl.h is not #include'd in this file.
-
- sl_von() is not mentioned in sl.h. It is defined in PRF.ASM.
-
- Note that Microsoft version 4.00 does not allow dummy names in
- these function prototypes.
- */
- #ifdef HAS_ANSI_PROTOTYPE
-
- void sl_bout (int);
- void sl_cout (char);
- void sl_dout (double);
- void sl_fout (double); /* Floats are passed as doubles. */
- void sl_iout (int);
- void sl_lout (long);
- void sl_pout (void *);
- char * sl_sbout(int);
- void sl_sout (char *);
- void sl_uiout(unsigned int);
- void sl_ulout(unsigned long);
-
- int sl_ret (char *);
- void sl_off (char *);
- void sl_on (char *);
- void sl_von (void);
-
- #else
-
- void sl_bout();
- void sl_cout();
- void sl_dout();
- void sl_fout();
- void sl_iout();
- void sl_lout();
- void sl_pout();
- void sl_sbout();
- void sl_sout();
-
- int sl_ret();
- void sl_off();
- void sl_on();
- void sl_von();
-
- #endif /* HAS_ANSI_PROTOTYPE */
-
- /*
- Declarations of internal routines.
- */
-
- #ifdef HAS_ANSI_PROTOTYPE
-
- static long sl_adjust (struct stat *, long);
- static void sl_check (char *);
- static struct stat *
- sl_find (char *, char *);
- static int sl_hash (char *);
- static int prefix (char *, char *);
- static struct stat *
- sl_new (char *);
- static void sl_set (char *, int);
- static void sl_s2out (char *, char *);
- static void sl_s3out (char *, char *, char *);
- static void sl_slout (int, char *);
- static int sl_visit (struct stat *, int, int);
- static int has_wild (char *);
- static int is_match (char *, char *);
- static void print_dots (int);
- static int strcmp_ (char *, char *);
- static int streq_ (char *, char *);
-
- #else
-
- static long sl_adjust();
- static void sl_check();
- static struct stat *
- sl_find();
- static int sl_hash();
- static int prefix();
- static struct stat *
- sl_new();
- static void sl_set();
- static void sl_s2out();
- static void sl_s3out();
- static void sl_slout();
- static int sl_visit();
- static int has_wild();
- static int is_match();
- static void print_dots();
- static int strcmp_();
- static int streq_();
-
- #endif /* HAS_ANSI_PROTOTYPE */
-
- /*
- ========== PART 2 ==========
- Internal (static) routines.
- */
-
- /*
- This routine defines the meaning of the TIME_ADJUST constant.
- Adjust the value of val by subtracting ((p->n_stat/1000)*TIME_ADJUST).
-
- The following code is complicated because only integer division is
- used. The division is done first to avoid overflow. If you know that
- overflow will not occur, you could simply define sl_adjust as:
-
- #define sl_adjust(p, val) (val-((p->n_stat * TIME_ADJUST) / 1000))
- */
-
- #ifndef TIME_ADJUST
- #define TIME_ADJUST 0
- #endif
-
- #define ADJ_1000(n) ( ((n)/1000) * TIME_ADJUST )
- #define ADJ_100(n) ( (((n)%1000)/100) * (TIME_ADJUST/10) )
- #define ADJ_10(n) ( (((n)%100)/10) * (TIME_ADJUST/100) )
- #define ADJ_1(n) ( ((n)%10) * (TIME_ADJUST/1000) )
-
- #if TIME_ADJUST == 0
-
- #define sl_adjust(p, val) (val)
-
- #else /* TIME_ADJUST > 0 */
-
- static long
- sl_adjust(p, val)
- struct stat *p;
- long val;
- {
- long n;
-
- /*
- This series of conditional statements eliminates warnings
- about "code has no effect" from the Turboc C compiler.
- */
-
- #if TIME_ADJUST > 1000
- n = val - ADJ_1000(p->n_stat) - ADJ_100(p->n_stat) -
- ADJ_10(p->n_stat) - ADJ_1(p->n_stat);
- #elif TIME_ADJUST > 100
- n = val - ADJ_1000(p->n_stat) - ADJ_100(p->n_stat) -
- ADJ_10(p->n_stat);
- #elif TIME_ADJUST > 10
- n = val - ADJ_1000(p->n_stat) - ADJ_100(p->n_stat);
- #elif TIME_ADJUST > 0
- n = val - ADJ_1000(p->n_stat);
- #else
- n = val;
- #endif
-
- return (n > 0) ? n : 0;
- }
-
- #endif /* TIME_ADJUST > 0 */
-
- #undef ADJ_1000
- #undef ADJ_100
- #undef ADJ_10
- #undef ADJ_1
-
- /*
- Check the string arguments to a tracing function.
-
- The check_s global variable points to a string containing the
- name of the macro responsible for invoking the check.
- */
- static void
- sl_check(register char *s)
- {
- register char c;
- register int i;
- char sbuf [40];
- char *old_s;
-
- STATS(t_check++);
- DEBUG(printf("sl_check(%s)\n", s));
-
- old_s = s;
-
- /* Check for null string. */
- if (!*s) {
- /* Write the error message. */
- sprintf(sbuf, "%p", s);
- sl_s3out("sl_check: ", check_s, ": null string @ ");
- sl_s2out(sbuf, "\n");
- exit(BAD_EXIT);
- }
-
- /* 6/27/89: allow up to 31 character names. */
- for (i = 0; i < 31; i++) {
- c = *s++;
- if (c == '\0') {
- return ;
- }
-
- /* Allow only identifiers and wild cards. */
- if (!isalnum(c) && c != '_' && c != '*' && c != '?') {
- sprintf(sbuf, "%p", s);
- sl_s3out("sl_check: ", check_s, ": bad character: ");
- sl_cout(c);
- sl_s3out(" in ", old_s, " @ ");
- sl_s2out(sbuf, "\n");
- exit(BAD_EXIT);
- }
- }
- sprintf(sbuf, "%p", s);
- sl_s3out("sl_check: ", check_s, ": run on argument: ");
- sl_s3out(old_s, " @ ", sbuf);
- sl_sout("\n");
- exit(BAD_EXIT);
- }
-
- /*
- Return a pointer to the node for s.
- Set the global check_s to macro_type.
- */
- static struct stat *
- sl_find(char *macro_type, char *s)
- {
- register int i;
- register struct stat *p, *q, *node;
- register int hash;
-
- struct stat * sl_new();
-
- STATS(t_find++);
- DEBUG(printf("sl_find(%s, %s)\n", macro_type, s));
-
- /* Update global error string. */
- check_s = macro_type;
-
- /* Search the proper index table. */
- hash = sl_hash(s);
- p = hash_tab [hash];
- if (p != NULL) {
- i = strcmp_(s, p -> name);
- if (i == 0) {
- DEBUG(printf("sl_find: returns %p\n", p));
- return p;
- }
- }
- if (p == NULL || i < 0) {
- sl_check(s);
- node = sl_new(s);
- hash_tab [hash] = node;
- node -> next = p;
- node -> n_disable = disable;
- DEBUG(printf("sl_find: returns %p\n", node));
- return node;
- }
-
- /* Search the list for the node. */
- for (q = p, p = p -> next; p; q = p, p = p -> next) {
- i = strcmp_(s, p -> name);
- if (i == 0) {
- return p;
- }
- else if (i < 0) {
- break;
- }
- }
-
- /* Not found. */
- sl_check(s);
- node = sl_new(s);
- q -> next = node;
- node -> next = p;
- node -> n_disable = disable;
- DEBUG(printf("sl_find: returns %p\n", node));
- return node;
- }
-
- /*
- Compute hash code for the string s.
- */
- static int
- sl_hash(register char *s)
- {
- register unsigned int hash;
-
- STATS(t_hash++);
-
- for (hash = 0; *s; ) {
- hash += hash + hash + (unsigned int) *s++;
- hash %= MAX_HASH;
- }
- return (int) hash;
- }
-
- /*
- Allocate a new node for tracepoint s from the static node table.
-
- If a match is found from the wildcard list, use that value for tracing.
- Otherwise, set the tracing field to zero (FALSE).
- */
- static struct stat *
- sl_new(char *s)
- {
- register struct stat * node, *p;
-
- STATS(t_new++);
- DEBUG(printf("sl_new(%s)\n", s));
-
- /* Not found. Point node at a new node. */
- if (cur_stat >= MAX_STAT) {
- sl_sout("sl_new: trace table overflow\n");
- exit(BAD_EXIT);
- }
-
- /* Create the new node. */
- node = sl__nodes + cur_stat;
- cur_stat++;
- node -> name = s;
- node -> n_stat = 0;
- node -> n_disable = disable;
-
- /*
- Search the wildcard list for a node which matches s.
- If found. Set trace field.
- */
- for (p = wildcard; p; p = p -> next) {
- if (is_match(p -> name, s)) {
- node -> trace = p -> trace;
- return node;
- }
- }
-
- /* No match. */
- node -> trace = 0;
- DEBUG(printf("sl_new: returns %p\n", node));
- return node;
- }
-
- /*
- Update the tracing status for string s and set the disable flags.
- Enable tracing if flag is TRUE.
-
- If s contains a wildcard, ALL nodes matching s have their enable
- field set to flag and a new entry for s is added to the wild card list.
- Otherwise, the single node (if it exists) which matches s has its
- enable field set to flag.
- */
- static void
- sl_set(char *s, int flag)
- {
- register struct stat * p;
- register char c;
- register int i;
-
- STATS(t_set++);
- DEBUG(printf("sl_set(%s, %d)\n", s, flag));
-
- /* Skip over the initial disable count. */
- disable = 0;
- while (*s >= '0' && *s <= '9') {
- c = *s++;
- disable = disable * 10 + (long)c - '0';
- }
- if (*s == '\0') {
- /* Global suppress. */
- g_disable = disable;
- disable = 0;
- return;
- }
-
- sl_check(s);
- if (!has_wild(s)) {
-
- /* No wild card. Just set one flag. */
- p = sl_find("SL_ON, SL_OFF or SL_PARSE", s);
- p -> trace = flag;
- if (flag == 0 && p -> n_disable != 0) {
- /* Ignore leading count. */
- p -> n_disable = 0;
- sl_sout("disable count ignored after off prefix\n");
- }
- disable = 0;
- return;
- }
-
- /* Search ALL hash lists. */
- for (i = 0; i < MAX_HASH; i++) {
- for (p = hash_tab [i]; p; p = p -> next) {
- /* Bug fix: 4/19/89
- wildcards possible only in first arg. */
- if (is_match(s, p -> name)) {
- p -> trace = flag;
- }
- }
- }
-
- /*
- Add new element at the head of the wildcard list.
- This will supercede any previous conflicting entries.
- */
- p = sl_new(s);
- p -> next = wildcard;
- wildcard = p;
- p -> trace = flag;
- if (p -> n_disable != 0) {
- /* Ignore leading count. */
- p -> n_disable = 0;
- sl_sout("disable count ignored in wildcard\n");
- }
- disable = 0;
- return;
- }
-
- /*
- Visit node p.
- Update statistics if stat_flag is TRUE.
- Enter a section of timing code if entry_flag is TRUE.
- Return TRUE if the node is currently enabled.
-
- Bug fix: New code marked with 10/18/88
-
- The old code updated statistics and reset sl_count only in sl_ret(),
- but that clearly can not be correct.
-
- The old code added time since the beginning of the deepest item on the
- stack to all entries on the stack. Example:
- f:
- a LOT of processing
- g:
- h:
- h exits;
-
- The bug updated h and g with f's time, which is wrong.
- */
- static int
- sl_visit(struct stat *p, int stat_flag, int entry_flag)
- {
- int i; /* bug fix: 10/18/88 */
- struct stat *p1; /* bug fix: 10/18/88 */
- char *p2; /* bug fix: 10/18/88 */
- unsigned long old_count; /* bug fix: 10/18/88 */
-
- if (troff || p == NULL) {
- return FALSE;
- }
-
- /* Update statistics if requested. */
- if (stat_flag) {
- p -> n_stat++;
- }
-
- /* Make an entry in the call stack for entry macros. */
- if (entry_flag && sl_level < MAX_BUG_LEVEL) {
-
- old_count = sl_count;
-
- /* bug fix: 10/18/88
- The following code is essentially
- identical to the code in sl_ret.
- */
-
- /* Update both timing statistics for the top of stack. */
- if (sl_level > 0) {
- p1 = call_stack [sl_level - 1];
- p1 -> n_times += old_count;
- p1 -> n_2times += old_count;
-
- /*
- Update the cumulative statistics of all outer
- routines EXCEPT recursive calls to the same
- function.
- */
- p2 = p1 -> name;
- for(i = 0; i < sl_level-1; i++) {
- p1 = call_stack[i];
- if (p1 -> name != p2) {
- p1 -> n_2times += old_count;
- }
- }
- }
- call_stack[sl_level++] = p;
- }
- /* bug fix: 10/18/88 */
- sl_count = 0;
-
- /* Return TRUE if macro should be enabled. */
- if (g_disable > 0) {
- g_disable--;
- if (p -> n_disable > 0) {
- p -> n_disable--;
- }
- return FALSE;
- }
- else if (p -> n_disable > 0) {
- p -> n_disable--;
- return FALSE;
- }
- else {
- return p -> trace;
- }
- }
-
- /*
- Return TRUE if string s1 contains a wildcard character, i.e., an
- asterisk or a question mark.
- */
- static int
- has_wild(register char *s)
- {
- register char c;
-
- STATS(t_wild++);
- DEBUG(printf("has_wild(%s)\n", s));
-
- for (;;) {
- c = *s++;
- if (c == '\0') {
- return FALSE;
- }
- else if (c == '*' || c == '?') {
- return TRUE;
- }
- }
- }
-
- /*
- Return TRUE if string s1 matches string s2 with wildcards possible in
- string s1.
- */
- static int
- is_match(register char *s1, register char *s2)
- {
- register char c;
-
- STATS(t_match++);
- DEBUG(printf("is_match(%s, %s)\n", s1, s2));
-
- for (;;) {
- c = *s1++;
- if (c == '\0') {
- return !*s2;
- }
- else if (c == '*') {
- /* Matches zero or more characters. */
- return TRUE;
- }
- else if (c == '?') {
- /* Matches exactly one character. */
- if (*s2 == '\0') {
- return FALSE;
- }
- else {
- s2++;
- }
- }
- else if (c != *s2++) {
- return FALSE;
- }
- }
- }
-
- /*
- Return TRUE if string p is a prefix of string s.
- */
- static int
- prefix(char *p, char *s)
- {
- while (*p) {
- if (*p++ != *s++) {
- return FALSE;
- }
- }
- return TRUE;
- }
-
- /*
- Print out n-1 periods.
- */
- static void
- print_dots(int n)
- {
- int i;
-
- for(i = 1; i < n; i++) {
- sl_cout('.');
- }
- }
-
- /*
- Compare s1 and s2.
- Return <0 ==0 >0
-
- WARNING: This routine MUST NOT call any Sherlock macro.
- (Calling STATS and DEBUG is permitted.)
- */
- static int
- strcmp_(register char *s1, register char *s2)
- {
- STATS(t_cmp++);
- DEBUG(printf("strcmp_(%s, %s)\n", s1, s2));
-
- while (*s1 == *s2) {
- if (*s1 == '\0') {
- return 0;
- }
- else {
- s1++;
- s2++;
- }
- }
- return ((int) *s1) - ((int) *s2);
- }
-
- /*
- Return TRUE if s1 == s2
-
- WARNING: This routine MUST NOT call any Sherlock macro.
- (Calling STATS and DEBUG is permitted.)
- */
- static int
- streq_(register char *s1, register char *s2)
- {
- STATS(t_eq++);
- DEBUG(printf("streq_(%s, %s)\n", s1, s2));
-
- while(*s1) {
- if (*s1++ != *s2++) {
- return FALSE;
- }
- }
- return !*s2;
- }
-
- /*
- ========== PART 3 ==========
- External routines common to both Mark I and Mark II versions.
- */
-
- /*
- SL_CLEAR macro--Clear all statistics.
- */
- void
- sl_clear(void)
- {
- int i;
- struct stat * p;
-
- for (i = 0; i < MAX_HASH; i++) {
- for (p = hash_tab[i]; p; p = p -> next) {
- p -> n_times = 0;
- p -> n_2times = 0;
- p -> n_stat = 0;
- }
- }
- }
-
- /*
- SL_DUMP macro--Print all statistics.
- */
-
- void
- sl_dump(void)
- {
- struct stat *p, *q, *q1;
- char *pname;
- int i;
- long tot_stats, percent, totp_stats;
- char sbuf1 [40], sbuf2 [40];
- #ifdef TIME_STATS
- long tot_times, tpercent, totp_times;
- long tot_2times, t2percent, totp_2times;
- #endif
-
- #ifdef BUG_HASH_DUMP
- int bucket_count;
- #endif
-
- sl_sout("\n\nReport of statistics:\n\n");
-
- /* Calculate grand total times. */
- tot_stats = 0;
- #ifdef TIME_STATS
- tot_times = 0;
- tot_2times = 0;
- #endif
-
- /* Scan all buckets. */
- for (i = 0; i < MAX_HASH; i++) {
-
- #ifdef BUG_HASH_DUMP
- bucket_count = 0;
- #endif
-
- for (p = hash_tab[i]; p; p = p -> next) {
-
- tot_stats += p -> n_stat;
- #ifdef TIME_STATS
- tot_times += sl_adjust(p, p->n_times); /* 8/3/89 */
- tot_2times += sl_adjust(p, p -> n_2times); /* 8/3/89 */
- #endif
-
- #ifdef BUG_HASH_DUMP
- bucket_count++;
- #endif
-
- /*
- Sort all and only those entries that will be printed.
- The sorting is done by creating a list in the alpha
- field of the stat nodes.
- */
- if ( p -> n_stat || p -> n_times ||
- p -> n_2times || p -> trace
- ) {
- pname = p -> name;
- for ( q1 = &a_list, q = q1 -> alpha;
- ;
- q1 = q, q = q -> alpha
- ) {
-
- if ( q == NULL ||
- strcmp_(pname, q -> name) < 0
- ) {
- q1 -> alpha = p;
- p -> alpha = q;
- break;
- }
- }
- }
-
- #ifdef BUG_HASH_DUMP
- if (bucket_count >= 9) {
- bin[9]++;
- }
- else {
- bin[bucket_count]++;
- }
- #endif
-
- }}
-
- /* Print the table in alphabetical order. */
- sl_slout(20, "tracepoints");
- sl_cout(' ');
- sl_slout(12, "ticks");
- sl_slout(5, " ");
-
- #ifdef TIME_STATS
- sl_slout(12, "times1");
- sl_slout(5, " ");
- sl_slout(10, "times2");
- sl_slout(5, " ");
- #endif
-
- sl_sout("tracing\n\n");
-
- totp_stats = 0;
- #ifdef TIME_STATS
- totp_times = 0;
- totp_2times = 0;
- #endif
-
- for (p = a_list.alpha; p; p = p -> alpha) {
- if (p -> n_stat || p -> n_times || p -> trace) {
- /* Print breakpoint name. */
- sl_slout(20, p -> name);
- sl_cout(' ');
-
- /* Print statistics. */
- if (tot_stats == 0) {
- percent = 0;
- }
- else {
- percent = ((p -> n_stat * 100) / tot_stats);
- totp_stats += percent;
- }
- #ifdef TIME_STATS
- if (tot_times == 0) {
- tpercent = 0;
- }
- else {
- tpercent =
- /* 8/3/89 */
- ((sl_adjust(p, p->n_times)*100) / tot_times);
- totp_times += tpercent;
- }
- if (tot_2times == 0) {
- t2percent = 0;
- }
- else {
- t2percent =
- /* 8/3/89 */
- ((sl_adjust(p, p->n_2times)*100) / tot_2times);
- totp_2times += t2percent;
- }
- #endif
-
- ltoa(p -> n_stat, sbuf1, 10);
- ltoa(percent, sbuf2, 10);
- sl_slout(8, sbuf1);
- sl_sout(" = ");
- sl_slout(3, sbuf2);
- sl_sout("% ");
-
- #ifdef TIME_STATS
- ltoa(sl_adjust(p,p->n_times), sbuf1, 10); /* 8/3/89 */
- ltoa(tpercent, sbuf2, 10);
- sl_slout(8, sbuf1);
- sl_sout(" = ");
- sl_slout(3, sbuf2);
- sl_sout("% ");
-
- ltoa(sl_adjust(p,p->n_2times), sbuf1, 10); /* 8/3/89 */
- ltoa(t2percent, sbuf2, 10);
- sl_slout(8, sbuf1);
- sl_sout(" = ");
- sl_slout(3, sbuf2);
- sl_sout("% ");
- #endif
-
- /* Indicate whether tracing was enabled. */
- if (p -> trace) {
- sl_slout(9, "ON\n");
- }
- else {
- sl_slout(9, "OFF\n");
- }
- }
- }
-
- /* Print the totals. */
- ltoa(tot_stats, sbuf1, 10);
- ltoa(totp_stats, sbuf2, 10);
- sl_slout(20, "TOTALS:");
- sl_sout(" ");
- sl_slout(8, sbuf1);
- sl_sout(" ");
- sl_slout(3, sbuf2);
- sl_sout("%");
-
- #ifdef TIME_STATS
- ltoa(tot_times, sbuf1, 10);
- ltoa(totp_times, sbuf2, 10);
- sl_sout(" ");
- sl_slout(8, sbuf1);
- sl_sout(" ");
- sl_slout(3, sbuf2);
-
- sl_sout("%");
-
- ltoa(tot_2times, sbuf1, 10);
- ltoa(totp_2times, sbuf2, 10);
- sl_sout(" ");
- sl_slout(8, sbuf1);
- sl_sout(" ");
- sl_slout(3, sbuf2);
- sl_sout("%\n\n");
-
- #endif
-
- /* Print the TIME_ADJUST Factor. */
- sl_sout("TIME_ADJUST is ");
- itoa(TIME_ADJUST, sbuf1, 10);
- sl_sout(sbuf1);
- sl_sout("\n\n");
-
- /* Print wildcard table. */
- sl_slout(20, "Wildcards");
- sl_sout(" tracing\n\n");
-
- for (p = wildcard; p; p = p -> next) {
- sl_slout(20, p -> name);
- sl_sout(" ");
- if (p -> trace) {
- sl_slout(8, "ON\n");
- }
- else {
- sl_slout(8, "OFF\n");
- }
- }
-
- #ifdef BUG_HASH_DUMP
- printf("\nHash statistics\n\n");
- for (i = 0; i < 10; i++) {
- printf("bin[%d] = %d\n", i, bin[i]);
- }
- #endif
-
- #ifdef BUG_STATS
-
- printf("\nInternal Variables\n\n");
-
- printf("t_buffer = %ld\n", t_buffer);
- printf("t_check = %ld\n", t_check);
- printf("t_cmp = %ld\n", t_cmp);
- printf("t_eq = %ld\n", t_eq);
- printf("t_find = %ld\n", t_find);
- printf("t_hash = %ld\n", t_hash);
- printf("t_init = %ld\n", t_init);
- printf("t_match = %ld\n", t_match);
- printf("t_new = %ld\n", t_new);
- printf("t_off = %ld\n", t_off);
- printf("t_on = %ld\n", t_on);
- printf("t_set = %ld\n", t_set);
- printf("t_wild = %ld\n\n", t_wild);
-
- printf("t_btick = %ld\n", t_btick);
- printf("t_btrace = %ld\n", t_btrace);
- printf("t_ntick = %ld\n", t_ntick);
- printf("t_ntrace = %ld\n", t_ntrace);
- printf("t_ptrace = %ld\n", t_ptrace);
- printf("t_pbtrace = %ld\n", t_pbtrace);
- printf("t_pntrace = %ld\n", t_pntrace);
- printf("t_pxtrace = %ld\n", t_pxtrace);
- printf("t_stat = %ld\n", t_stat);
- printf("t_tick = %ld\n", t_tick);
- printf("t_trace = %ld\n", t_trace);
- printf("t_xtrace = %ld\n\n", t_xtrace);
-
- #endif
-
- }
-
-
- /*
- SL_INIT macro--Initialize the statistics routines.
- */
- void
- sl_init(char * version)
- {
- int i;
-
- STATS(t_init++);
- DEBUG(printf("sl_init()\n"));
-
- sl_s3out("Sherlock support routines version ", SL_VERSION_NAME, "\n");
-
- if (strcmp(version, SL_VERSION_NAME) != 0) {
- sl_s2out("sl_init: Header version ", version);
- sl_sout(" does not match version of support routines.\n");
- exit(BAD_EXIT);
- }
-
- /* Initialize the hash table. */
- for (i = 0; i < MAX_HASH; i++) {
- hash_tab [i] = NULL;
- }
- a_list.alpha = NULL;
- a_list.next = NULL;
- a_list.name = NULL;
-
- #ifdef TIME_STATS
- /* Initialize the interrupt vectors. See. prf.asm */
- sl_von();
- DEBUG(sl_sout("Trap vectors installed.\n"));
- #endif
-
- }
-
- /*
- SL_OFF macro.
- Turn tracing off for one variable or a class of variables.
- */
- void
- sl_off(char *s)
- {
- STATS(t_off++);
- DEBUG(printf("sl_off(%s)\n", s));
-
- if (streq_(s, "trace")) {
- sl_sout("Disabling ALL tracing...\n");
- troff = TRUE;
- return;
- }
- sl_s3out("Disabling trace of ", s, "\n");
-
- check_s = "TRACE_OFF";
- sl_set(s, 0);
- }
-
- /*
- SL_ON macro.
- Turn tracing on for one variable or a class of variables.
- */
- void
- sl_on(char *s)
- {
- STATS(t_on++);
- DEBUG(printf("sl_on(%s)\n", s));
-
- if (streq_(s, "trace")) {
- sl_sout("Enabling ALL tracing...\n");
- troff = FALSE;
- return;
- }
- sl_s3out("Enabling trace of ", s, "\n");
-
- check_s = "TRACE_ON";
- sl_set(s, 1);
- }
-
- /*
- SL_PARSE macro--Parse the command list.
- argcp points to the argc count.
- argv contains pointers to the arguments.
- on_str and off_str are the on_prefix and off_prefix respectively.
- */
- void
- sl_parse(int *argcp, char **argv, char *on_str, char *off_str)
- {
- char ** base;
- char * arg;
- int argc;
- int on_len, off_len;
-
- on_len = strlen(on_str);
- off_len = strlen(off_str);
-
- argc = *argcp;
- argc--;
- argv++;
- base = argv;
- while (argc-- > 0) {
- arg = *argv++;
-
- if (prefix(on_str, arg)) {
- if (!*(arg + on_len)) {
- sl_s3out("Lone '", on_str, "'\n");
- exit(BAD_EXIT);
- }
- sl_on(arg + on_len);
-
- /* One less argument for the program. */
- (*argcp)--;
- }
- else if (prefix(off_str, arg)) {
- if (!*(arg + off_len)) {
- sl_s3out("Lone '", off_str, "'\n");
- exit(BAD_EXIT);
- }
- sl_off(arg + off_len);
-
- /* One less argument for the program. */
- (*argcp)--;
-
- }
- else {
- /* Compact original argv vector. */
- *base++ = arg;
- }
- }
- }
-
- /*
- The following macros are the same in both versions because there
- is no need to pass a handle to the support routine--the proper handle
- should be on top of the call stack.
- */
-
- /*
- TRACEPX macro.
- */
- int
- sl_pxtrace(char *s)
- {
- STATS(t_pxtrace++);
- DEBUG(printf("sl1pxtrace(%s)\n", s));
-
- if (sl_ret(s)) {
- print_dots(sl_level);
- sl_s2out(s, ": ");
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /*
- Check for proper stack alignment using the entry name s.
- Return TRUE if tracing is enabled.
- */
- int
- sl_ret(char *s)
- {
- register int i;
- register struct stat *p, *p1;
- char *p2;
- unsigned long old_count;
-
- if (troff) {
- return FALSE;
- }
- else if (sl_level <= 0) {
- sl_s3out(
- "Sherlock call stack underflow at exit point ", s, "\n");
- return FALSE;
- }
-
- p = call_stack [sl_level-1];
- if (!streq_(p -> name, s)) {
- sl_s3out("sl_ret: Entry/Exit mismatch at exit point ", s, "\n");
- sl_sout("Check for missing or misnamed exit macros.\n");
- sl_sout("Dump of call stack: \n\n");
- for (i = sl_level - 1; i >= 0; i--) {
- sl_s2out(call_stack [i] -> name, "\n");
- }
- sl_sout("\n");
- exit(1);
- }
- else {
- old_count = sl_count;
- /* Update both timing statistic. */
- p1 = call_stack [sl_level - 1];
- p1 -> n_times += old_count;
- p1 -> n_2times += old_count;
-
- /*
- Update the cumulative statistics of all nested routines
- EXCEPT recursive calls to the same function.
- */
- p2 = p1 -> name;
- for(i = 0; i < sl_level-1; i++) {
- p1 = call_stack[i];
- if (p1 -> name != p2) {
- p1 -> n_2times += old_count;
-
- DEBUG(printf("sl_ret: add %ld to cumulative for %s\n",
- old_count, p1 -> name));
-
- }
- }
- sl_count = 0;
- sl_level--;
- }
-
- /* Return TRUE if we should enable the macro. */
- if (g_disable > 0) {
- g_disable--;
- if (p -> n_disable > 0) {
- p -> n_disable--;
- }
- return FALSE;
- }
- else if (p -> n_disable > 0) {
- p -> n_disable--;
- return FALSE;
- }
- else {
- return p -> trace;
- }
- }
-
- /*
- TICKX macro--Exit a nesting level and print s.
- */
- void
- sl_x(char *s)
- {
- if (sl_ret(s)) {
- print_dots(sl_level);
- sl_s2out(s, ": exits\n");
- }
- }
-
- /*
- RETURN_BOOL macro.
- Exit a nesting sl_level and print a boolean (int).
- */
- int
- sl_xb(char *s, int b)
- {
- if (sl_ret(s)) {
- print_dots(sl_level);
- if (b) {
- sl_s2out(s, ": returns TRUE\n");
- }
- else {
- sl_s2out(s, ": returns FALSE\n");
- }
- }
- return b;
- }
-
- /*
- RETURN_CHAR macro.
- Exit a nesting level and print a character.
- */
- char
- sl_xc(char *s, char c)
- {
- char buffer[2];
-
- if (sl_ret(s)) {
- print_dots(sl_level);
- buffer[0] = c;
- buffer[1] = '\0';
- sl_s3out(s, ": returns ", buffer);
- sl_sout("\n");
- }
- return c;
- }
-
- /*
- EXIT_DOUBLE macro.
- Exit a nesting sl_level and print a double.
- */
- double
- sl_xd(char *s, double d)
- {
- char buffer [100];
-
- if (sl_ret(s)) {
- print_dots(sl_level);
- sprintf(buffer, "%f", d);
- sl_s3out(s, ": returns ", buffer);
- sl_sout("\n");
- }
- return d;
- }
-
- /*
- RETURN_INT macro.
- Exit a nesting level and print an int.
- */
- int
- sl_xi(char *s, int n)
- {
- char buffer [40];
-
- if (sl_ret(s)) {
- print_dots(sl_level);
- itoa(n, buffer, 10);
- sl_s2out(s, ": returns ");
- sl_s2out(buffer, "\n");
- }
- return n;
- }
-
- /*
- RETURN_LONG macro.
- Exit a nesting level and print a long.
- */
- long
- sl_xl(char *s, long l)
- {
- char buffer [40];
-
- if (sl_ret(s)) {
- print_dots(sl_level);
- ltoa(l, buffer, 10);
- sl_s2out(s, ": returns ");
- sl_s2out(buffer, "\n");
- }
- return l;
- }
-
- /*
- RETURN_PTR macro.
- Exit a nesting level and print a pointer.
- */
- void *
- sl_xp(char *s, void *pv)
- {
- char buffer [100];
-
- if (sl_ret(s)) {
- print_dots(sl_level);
- sprintf(buffer, "%p", pv);
- sl_s3out(s, ": returns ptr: ", buffer);
- sl_sout("\n");
- }
- return pv;
- }
-
- /*
- RETURN_sTRING macro.
- Exit a nesting level and print a string.
- */
- char *
- sl_xs(char *s1, char *s2)
- {
- if(sl_ret(s1)) {
- print_dots(sl_level);
- sl_s3out(s1, ": returns ", s2);
- sl_sout("\n");
- }
- return s2;
- }
-
- /*
- TRACEX macro.
- */
- int
- sl_xtrace(char *s)
- {
- STATS(t_xtrace++);
- DEBUG(printf("sl_xtrace(%s)\n", s));
-
- return sl_ret(s);
- }
-
- /*
- RETURN_UINT macro.
- Exit a nesting level and print an unsigned int.
- */
- unsigned int
- sl_xui(char *s1, unsigned int ui)
- {
- char buffer [100];
-
- if(sl_ret(s1)) {
- print_dots(sl_level);
- sprintf(buffer, "(unsigned) %u", ui);
- sl_s3out(s1, ": returns ", buffer);
- sl_sout("\n");
- }
- return ui;
- }
-
- /*
- RETURN_ULONG macro.
- Exit a nesting level and print an unsigned int.
- */
- unsigned long
- sl_xul(char *s1, unsigned long ul)
- {
- char buffer [100];
-
- if(sl_ret(s1)) {
- print_dots(sl_level);
- sprintf(buffer, "(unsigned) %lu", ul);
- sl_s3out(s1, ": returns ", buffer);
- sl_sout("\n");
- }
- return ul;
- }
-
- /*
- RETURN_VOID macro--Exit a nesting level and print void.
- */
- void
- sl_xv(char *s)
- {
- if (sl_ret(s)) {
- print_dots(sl_level);
- sl_s2out(s, ": returns void\n");
- }
- }
-
- /*
- ========== PART 4 ==========
- Mark I versions of routines.
- */
- #ifdef MARKI
-
- /*
- STATB macro--Enter a new nesting level.
- (Mark I Version.)
- */
- void
- sl1bstat(char *s)
- {
- STATS(t_bstat++);
- DEBUG(printf("sl1bstat(%s)\n", s));
-
- sl_visit(sl_find("STATB", s), STAT_FLAG, ENTRY_FLAG);
- }
-
- /*
- BTICK and ENTER macros--Enter a new nesting level.
- (Mark I Version.)
- */
- void
- sl1btick(char *s)
- {
- STATS(t_btick++);
- DEBUG(printf("sl1btick(%s)\n", s));
-
- if (sl_visit(sl_find("TICKB", s) , STAT_FLAG, ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ":\n");
- }
- }
-
- /*
- TRACEB macros.
- Enter a new nesting level.
- (Mark I Version.)
- */
- int
- sl1btrace(char *s)
- {
- STATS(t_btrace++);
- DEBUG(printf("sl1btrace(%s)\n", s));
-
- return sl_visit(sl_find("TRACEB", s), STAT_FLAG, ENTRY_FLAG);
- }
-
- /*
- TICKN macro--TICK with no statistics.
- (Mark I Version.)
- */
- void
- sl1ntick(char *s)
- {
- STATS(t_ntick++);
- DEBUG(printf("sl1ntick(%s)\n", s));
-
- if (sl_visit(sl_find("TICKN", s), NO_STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ":\n");
- }
- }
-
- /*
- TRACEN macro--TRACE with no statistics.
- (Mark I Version.)
- */
- int
- sl1ntrace(char *s)
- {
- STATS(t_ntrace++);
- DEBUG(printf("sl1ntrace(%s)\n", s));
-
- return sl_visit(sl_find("TRACEN", s), NO_STAT_FLAG, NO_ENTRY_FLAG);
- }
-
- /*
- TRACEPB and ENTER_TRACE macros.
- Enter a new nesting level.
- (Mark I Version.)
- */
- int
- sl1pbtrace(char *s)
- {
- STATS(t_pbtrace++);
- DEBUG(printf("sl1pbtrace(%s)\n", s));
-
- if (sl_visit(sl_find("TRACEPB", s), STAT_FLAG, ENTRY_FLAG)) {
- print_dots(sl_level - 1);
- sl_s2out(s, ": ");
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /*
- TRACEPN--TRACEP with no statistics.
- (Mark I Version.)
- */
- int
- sl1pntrace(char *s)
- {
- STATS(t_pntrace++);
- DEBUG(printf("sl1pntrace(%s)\n", s));
-
- if (sl_visit(sl_find("TRACEPN", s), NO_STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ": ");
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /*
- TRACEP macro--TRACE with printing of tracepoint's name.
- (Mark I Version.)
- */
- int
- sl1ptrace(char *s)
- {
- STATS(t_ptrace++);
- DEBUG(printf("sl1ptrace(%s)\n", s));
-
- if (sl_visit(sl_find("TRACEP", s), STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ": ");
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /*
- STAT macro--Update one statistic.
- (Mark I Version.)
- */
- void
- sl1stat(char *s)
- {
- STATS(t_stat++);
- DEBUG(printf("sl1stat(%s)\n", s));
-
- sl_visit(sl_find("STAT", s), STAT_FLAG, NO_ENTRY_FLAG);
- }
-
- /*
- TICK macro--Update one statistic and print the tracepoint name.
- (Mark I Version.)
- */
- void
- sl1tick(char *s)
- {
- STATS(t_tick++);
- DEBUG(printf("sl1tick(%s)\n", s));
-
- if (sl_visit(sl_find("TICK", s), STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level - 1);
- sl_s2out(s, ":\n");
- }
- }
-
- /*
- TRACE macro--Return TRUE if tracing s.
- (Mark I Version.)
- */
- int
- sl1trace(char *s)
- {
- STATS(t_trace++);
- DEBUG(printf("sl1trace(%s)\n", s));
-
- return sl_visit(sl_find("TRACE", s), STAT_FLAG, NO_ENTRY_FLAG);
- }
-
-
- #endif /* MARKI */
-
- /*
- ========== PART 5 ==========
- Mark II versions of routines.
- */
- #ifdef MARKII
-
- /*
- STATB macro--Enter a new nesting level.
- (Mark II Version).
- */
- void
- sl2bstat(struct stat **pp, char *s)
- {
- STATS(t_bstat++);
- DEBUG(printf("sl2bstat(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TICKB", s);
- }
- sl_visit(*pp, STAT_FLAG, ENTRY_FLAG);
- }
-
- /*
- TICKB or ENTER macros--Enter a new nesting level.
- (Mark II Version).
- */
- void
- sl2btick(struct stat **pp, char *s)
- {
- STATS(t_btick++);
- DEBUG(printf("sl2btick(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TICKB", s);
- }
-
- if (sl_visit(*pp, STAT_FLAG, ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ":\n");
- }
- }
-
- /*
- TRACEB macro--Enter a new nesting level.
- (Mark II Version).
- */
- int
- sl2btrace(struct stat **pp, char *s)
- {
- STATS(t_btrace++);
- DEBUG(printf("sl2btrace(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TRACEB", s);
- }
- return sl_visit(*pp, STAT_FLAG, ENTRY_FLAG);
- }
-
- /*
- TICKN macro.
- (Mark II Version.)
- */
- void
- sl2ntick(struct stat **pp, char * s)
- {
- STATS(t_ntick++);
- DEBUG(printf("sl2ntick(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TICKN", s);
- }
-
- if (sl_visit(*pp, NO_STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ":\n");
- }
- }
-
- /*
- TRACEN macro.
- (Mark II Version.)
- */
- int
- sl2ntrace(struct stat **pp, char *s)
- {
- STATS(t_ntrace++);
- DEBUG(printf("sl2ntrace(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TRACEN", s);
- }
- return sl_visit(*pp, NO_STAT_FLAG, NO_ENTRY_FLAG);
- }
-
- /*
- TRACEPB and ENTER_TRACE macros--Enter a new nesting level.
- (Mark II Version).
- */
- int
- sl2pbtrace(struct stat **pp, char *s)
- {
- STATS(t_pbtrace++);
- DEBUG(printf("sl2pbtrace(%s)\n", s));
-
- /* Find the proper node. Allocate one if needed. */
- if (*pp == NULL) {
- *pp = sl_find("TRACEPB", s);
- }
- if (sl_visit(*pp, STAT_FLAG, ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ": ");
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /*
- TRACEPN macro.
- (Mark II Version.)
- */
- int
- sl2pntrace(struct stat **pp, char *s)
- {
- STATS(t_pntrace++);
- DEBUG(printf("sl2pntrace(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TRACEPN", s);
- }
- if (sl_visit(*pp, NO_STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ": ");
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /*
- TRACEP macro--TRACE with printing of tracepoint's name.
- (Mark II Version.)
- */
- int
- sl2ptrace(struct stat **pp, char *s)
- {
- STATS(t_ptrace++);
- DEBUG(printf("sl2ptrace(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TRACEP", s);
- }
- if (sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ": ");
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /*
- STAT macro--Update one statistic.
- (Mark II Version.)
- */
- void
- sl2stat(struct stat **pp, char * s)
- {
- STATS(t_stat++);
- DEBUG(printf("sl2stat(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("STAT", s);
- }
- sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG);
- }
-
- /*
- TICK macro--Update one statistic and print tracepoint's name.
- (Mark II Version.)
- */
- void
- sl2tick(struct stat **pp, char * s)
- {
- STATS(t_tick++);
- DEBUG(printf("sl2tick(%s)\n", s));
-
- /* Find the proper node. Allocate one if needed. */
- if (*pp == NULL) {
- *pp = sl_find("TICK", s);
- }
- if (sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG)) {
- print_dots(sl_level-1);
- sl_s2out(s, ":\n");
- }
- }
-
- /*
- TRACE macro--Return TRUE if tracing s.
- (Mark II Version.)
- */
- int
- sl2trace(struct stat **pp, char *s)
- {
- STATS(t_trace++);
- DEBUG(printf("sl2trace(%s)\n", s));
-
- if (*pp == NULL) {
- *pp = sl_find("TRACE", s);
- }
- return sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG);
- }
-
- #endif /* MARKII */
-
- /*
- ========== PART 6 ==========
- Output routines.
- */
-
- /*
- Output a character to the standard place.
-
- This is the only routine you should change in order to use different
- routines for output. All output eventually goes through this routine.
- */
- void
- sl_cout(char c)
- {
- putchar(c);
- }
-
- /*
- Output a comma, followed by a space.
- SPP generates a call to this routine to save space.
- */
- void
- sl_csout(void)
- {
- sl_sout(", ");
- }
-
-
- /*
- Output a bool.
- */
- void
- sl_bout(int b)
- {
- if (b) {
- sl_sout("TRUE");
- }
- else {
- sl_sout("FALSE");
- }
- }
-
- /*
- Output a double.
- */
- void
- sl_dout(double d)
- {
- char buf [100];
-
- sprintf(buf, "%f", d);
- sl_sout(buf);
- }
-
- /*
- Output a float. (Floats are converted to double.)
- */
- void
- sl_fout(double f)
- {
- char buf [100];
-
- sprintf(buf, "%f", f);
- sl_sout(buf);
- }
-
- /*
- Output an integer.
- */
- void
- sl_iout(int i)
- {
- char buf [100];
-
- sprintf(buf, "%d", i);
- sl_sout(buf);
- }
-
- /*
- Output a left (open) parenthesis.
- SPP generates a call to this routine to save space.
- */
- void
- sl_lpout(void)
- {
- sl_cout('(');
- }
-
- /*
- Output a long.
- */
- void
- sl_lout(long l)
- {
- char buf [100];
-
- sprintf(buf, "(long) %ld", l); /* bug fix: 2/10/89 */
- sl_sout(buf);
- }
-
- /*
- Output a pointer.
- */
- void
- sl_pout(void *p)
- {
- char buf [100];
-
- sprintf(buf, "(pointer) %p", p);
- sl_sout(buf);
- }
-
- /*
- Output a right parenthesis and a newline.
- SPP generates a call to this routine to save space.
- */
- void
- sl_rpout(void)
- {
- sl_sout(")\n");
- }
-
- /*
- Return a pointer to a string corresponding to a bool.
- */
- char *
- sl_sbout(int b)
- {
- return (b ? "TRUE" : "FALSE");
- }
-
- /*
- Output a string.
- */
- void
- sl_sout(char *s)
- {
- while (*s) {
- sl_cout(*s++);
- }
- }
-
- /*
- Output two strings.
- */
- static void
- sl_s2out(char *s1, char *s2)
- {
- sl_sout(s1);
- sl_sout(s2);
- }
-
- /*
- Output three strings.
- */
- static void
- sl_s3out(char *s1, char *s2, char *s3)
- {
- sl_sout(s1);
- sl_sout(s2);
- sl_sout(s3);
- }
-
- /*
- Output string s right justified in a field of size n.
- */
- static void
- sl_slout(int n, char *s)
- {
- int pad;
-
- for (pad = n - strlen(s); pad > 0; pad--) {
- sl_cout(' ');
- }
- sl_sout(s);
- }
-
- /* 2/10/89
-
- Output an unsigned int.
- */
- void
- sl_uiout(unsigned u)
- {
- char buf [100];
-
- sprintf(buf, "(unsigned) %u", u);
- sl_sout(buf);
- }
-
- /* 2/10/89
-
- Output an unsigned int.
- */
- void
- sl_ulout(unsigned long u)
- {
- char buf [100];
-
- sprintf(buf, "(unsigned long) %lu", u);
- sl_sout(buf);
- }
-